package com.crm.crm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.crm.crm.domain.*;
import com.crm.crm.domain.dto.business.BusinessMessageDto;
import com.crm.crm.domain.dto.contract.ContractDto;
import com.crm.crm.domain.dto.contract.ContractPageQueryParams;
import com.crm.crm.domain.dto.contract.ContractSaveDTO;
import com.crm.crm.domain.dto.report.ContractStatisticsListDto;
import com.crm.crm.domain.vo.*;
import com.crm.crm.domain.vo.contract.ContractReportResponse;
import com.crm.crm.domain.vo.contract.ContractVo;
import com.crm.crm.domain.vo.PageResult;
import com.crm.crm.domain.vo.SubjectCountVo;
import com.crm.crm.domain.vo.business.BusinessVo;
import com.crm.crm.mapper.BusinessMapper;
import com.crm.crm.mapper.ContractMapper;
import com.crm.crm.mapper.CourseMapper;
import com.crm.crm.mapper.IndexMapper;
import com.crm.crm.service.ContractService;
import com.crm.crm.domain.vo.SeriesData;
import com.crm.crm.util.GetDateRange;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> implements ContractService {

    private final ContractMapper contractMapper;
    private final CourseServicelmpl courseService;
    private final DeptServicelmpl deptService;
    private final BusinessServicelmpl businessServicelmpl;
    private final BusinessMapper businessMapper;
    private final CourseServicelmpl courseServicelmpl;
    private final DeptServicelmpl deptServicelmpl;
    private final UserServicelmpl userServicelmpl;
    private final IndexMapper  indexMapper;

    @Override
    public PageResult<Contract> pageQuery(ContractPageQueryParams pageQueryParams) {
        Page<Contract> page = new Page<>(pageQueryParams.getPageNum(), pageQueryParams.getPageSize());
        String begin = pageQueryParams.getBeginCreateTime();
        String end = pageQueryParams.getEndCreateTime();
        log.info("开始时间范围: {}", begin);
        log.info("结束时间范围: {}", end);
        PageResult<Contract> pageResult = new PageResult<>();
        LambdaQueryWrapper<Contract> wrapper = new LambdaQueryWrapper<>();
        //时间范围
        wrapper.ge(StrUtil.isNotEmpty(begin), Contract::getCreateTime, begin)
                .le(StrUtil.isNotEmpty(end), Contract::getCreateTime, end)
                //合同编号、姓名、手机号、学科、课程id
                .like(StrUtil.isNotEmpty(pageQueryParams.getContractNo()), Contract::getContractNo, pageQueryParams.getContractNo())
                .like(StrUtil.isNotEmpty(pageQueryParams.getName()), Contract::getName, pageQueryParams.getName())
                .eq(StrUtil.isNotEmpty(pageQueryParams.getPhone()), Contract::getPhone, pageQueryParams.getPhone())
                .eq(StrUtil.isNotEmpty(pageQueryParams.getSubject()), Contract::getSubject, pageQueryParams.getSubject())
                .eq(pageQueryParams.getCourseId() != null, Contract::getCourseId, pageQueryParams.getCourseId());
        Page<Contract> contractPage = contractMapper.selectPage(page, wrapper);
        pageResult.setTotal(contractPage.getTotal());
        pageResult.setRows(contractPage.getRecords());
        return pageResult;
    }

    /**
     * 新增合同
     *
     * @param contractDto
     */
    @Override
    public void addContract(ContractDto contractDto) {
        contractDto.setCreateTime(new Date());
        Contract contract = new Contract();
        BeanUtil.copyProperties(contractDto, contract);
        // 构建查询条件，判断合同编号是否已存在
        QueryWrapper<Contract> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("contract_no", contract.getContractNo());
        // 执行查询
        Long count = contractMapper.selectCount(queryWrapper);
        // 根据查询结果进行处理
        if (count > 0) {
            // 合同编号已存在，返回错误信息
            log.info("合同编号重复，{}", contract.getContractNo());
            throw new RuntimeException("合同编号已存在");
        }
        contractMapper.insert(contract);
    }


    //这客户统计时候调用的分页查询方法
    @Override
    public Page<Contract> list(ContractStatisticsListDto dto, Page<Contract> page) {
        LambdaQueryWrapper<Contract> wrapper = new LambdaQueryWrapper<>();

        // 根据起始时间查询。判断是否有内容，没有则查询所有
        // 时间范围查询
        if (StringUtils.isNotEmpty(dto.getBeginCreateTime())) {
            wrapper.ge(Contract::getFinishTime, dto.getBeginCreateTime());
        }
        if (StringUtils.isNotEmpty(dto.getEndCreateTime())) {
            wrapper.le(Contract::getFinishTime, dto.getEndCreateTime() + " 23:59:59");
        }

//        根据渠道查询
        wrapper.eq(StringUtils.isNotEmpty(dto.getChannel()), Contract::getChannel, dto.getChannel());
        if (dto.getDeptId() != null) {
            log.info("部门id：{}", dto.getDeptId());
            //        根据部门id查询时候，考虑其可能存在子部门，需要同时查询子部门，调用递归方法
            List<Long> users = deptService.getAllDeptIdsInDeptAndSubDepts(dto.getDeptId());
            log.info("本部门和下属部门id：{}", users);
//        根据部门进行查询
            wrapper.in(users.size() > 0, Contract::getDeptId, users);
        }
        //        根据所属人模糊查询
        wrapper.like(StringUtils.isNotEmpty(dto.getCreateBy()), Contract::getCreateBy, dto.getCreateBy());
        return contractMapper.selectPage(page, wrapper);
    }

    //    统计当前时间段类新增客户和累计客户数
    @Override
    public ContractReportResponse contractStatistics(String beginCreateTime, String endCreateTime) {
        // Step 1: 获取时间范围内所有日期
        List<String> dates = GetDateRange.generateDateRange(beginCreateTime, endCreateTime);

        // Step 2: 查询时间范围内所有合同的创建时间
        List<Contract> contracts = getContractsInDateRange(beginCreateTime, endCreateTime);

        // Step 3: 构建每天的新增客户数
        List<Integer> newCustomers = new ArrayList<>();
        for (String date : dates) {
            int finalCount = countContractsOnDay(contracts, date);
            newCustomers.add(finalCount);
        }

        // Step 4: 构建每天的累计客户数
        List<Integer> totalCustomers = new ArrayList<>();
        int cumulativeCount = 0;
        for (Integer dailyCount : newCustomers) {
            cumulativeCount += dailyCount;
            totalCustomers.add(cumulativeCount);
        }

        // Step 5: 构造响应对象
        ContractReportResponse response = new ContractReportResponse();
        SeriesData newData = new SeriesData();
        SeriesData totalData = new SeriesData();

        newData.setName("新增客户数");
        newData.setData(newCustomers);

        totalData.setName("客户总数");
        totalData.setData(totalCustomers);

        response.setXAxis(dates);
        response.setSeries(List.of(newData, totalData));

        return response;
    }


    //查询时间范围内所有合同
    private List<Contract> getContractsInDateRange(String beginTime, String endTime) {
        LambdaQueryWrapper<Contract> wrapper = new LambdaQueryWrapper<>();
        wrapper.between(Contract::getFinishTime,
                beginTime + " 00:00:00",
                endTime + " 23:59:59");
        return contractMapper.selectList(wrapper);
    }

    //按天统计新增客户数
    private Integer countContractsOnDay(List<Contract> contracts, String dateStr) {
        return (int) contracts.stream()
                .filter(contract -> {
                    if (contract.getFinishTime() == null) return false;

                    // 使用 DateTimeFormatter 格式化 finishTime
                    String finishTimeStr = new SimpleDateFormat("yyyy-MM-dd").format(contract.getFinishTime());

                    // 比较是否是同一天
                    return finishTimeStr.equals(dateStr);
                })
                .count();
    }

    //统计客户选择的学科
    @Override
    public List<SubjectCountVo> countProject(String beginCreateTime, String endCreateTime) {
        return contractMapper.countProject(beginCreateTime, endCreateTime);
    }

    //统计客户的来源渠道
    @Override
    public List<Map<Integer, String>> CountChannel(String beginCreateTime, String endCreateTime) {
        List<Map<Integer, String>> channelCount = contractMapper.CountChannel(beginCreateTime, endCreateTime);
        return channelCount;
    }

    //统计客户来源的活动
    @Override
    public List<Map<String, Integer>> CountActivitystics(String beginCreateTime, String endCreateTime) {
        List<Map<String, Integer>> activityCount = contractMapper.CountActivitystics(beginCreateTime, endCreateTime);

        return activityCount;
    }

    //    统计所属人的分页查询
    @Override
    public List<CountShipVo> countOwner(String beginCreateTime, String endCreateTime) {
        return contractMapper.countOwner(beginCreateTime, endCreateTime);

    }

    //    统计所属部门的分页查询
    @Override
    public List<CountShipVo> countDept(String beginCreateTime, String endCreateTime) {
        return contractMapper.countDept(beginCreateTime, endCreateTime);
    }

    //    统计所属渠道的分页查询
    @Override
    public List<CountShipVo> countChannel(String beginCreateTime, String endCreateTime) {
        return contractMapper.countChannel(beginCreateTime, endCreateTime);
    }

    //    销售统计的曲线图，统计了每天的销售金额
    @Override
    public ContractReportResponse salesStatistics(String beginCreateTime, String endCreateTime) {
        List<Map<String, Object>> result = contractMapper.salesAmountByDate(beginCreateTime, endCreateTime);

        List<String> dates = result.stream()
                .map(map -> ((java.sql.Date) map.get("date")).toLocalDate().toString())
                .toList();

        List<BigDecimal> amounts = result.stream()
                .map(map -> (BigDecimal) map.get("amount"))
                .toList();

        List<Integer> amountIntegers = amounts.stream()
                .map(BigDecimal::intValue)
                .toList();

        ContractReportResponse response = new ContractReportResponse();
        response.setXAxis(dates);

        SeriesData seriesData = new SeriesData();
        seriesData.setName("销售金额");
        seriesData.setData(amountIntegers);

        response.setSeries(List.of(seriesData));

        return response;
    }



    //查询合同详情(根据id)
    @Override
    public ContractVo getContractDetailsById(Long id) {
        Contract contract = contractMapper.selectById(id);
        ContractVo contractVo = new ContractVo();
        BeanUtil.copyProperties(contract, contractVo);
        return contractVo;
    }

    @Override
    public void updateContractById(ContractSaveDTO contractSaveDTO) {
        log.info("合同DTO{}", contractSaveDTO);
        Long id = contractSaveDTO.getId();
        Contract contract = contractMapper.selectById(id);
        if (contract == null) {
            throw new RuntimeException("合同不存在");
        }
        BeanUtil.copyProperties(contractSaveDTO, contract);
        log.info("修改后的合同：{}", contract);
        contractMapper.updateById(contract);
    }

    /**
     * 商机转客户新增合同
     *
     * @param id
     * @param contractDto
     */
    @Override
    public void changeContract(Long id, ContractDto contractDto) {
        LambdaQueryWrapper<BusinessOpportunity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BusinessOpportunity::getId, id);
        BusinessOpportunity businessOpportunity = businessMapper.selectOne(wrapper);
        log.info("商机信息：{}", businessOpportunity);
        Contract contract = new Contract();
        //获取前端返回值
        contractDto.setContractNo(contractDto.getContractNo());
        contractDto.setPhone(contractDto.getPhone());
        contractDto.setFileName(contractDto.getFileName());
        BeanUtil.copyProperties(contractDto, contract);
        //设置其它字段
        contract.setName(businessOpportunity.getName());
        contract.setSubject(businessOpportunity.getSubject());
        contract.setCourseId(businessOpportunity.getCourseId());
        log.info("课程Id{}", businessOpportunity.getCourseId());
        //调用方法获取课程id
        Course course = courseServicelmpl.getById(contract.getCourseId());
        contract.setCoursePrice(course.getPrice());
        log.info("课程价格{}", course.getPrice());
        contract.setBusinessId(businessOpportunity.getId());
        contract.setChannel(businessOpportunity.getChannel());
        //设置部门id
        SysUser sysUser = userServicelmpl.getUserById(businessOpportunity.getOwner());
        contract.setDeptId(sysUser.getDeptId().intValue());
        contract.setCreateBy(businessOpportunity.getOwner());
        contract.setCreateTime(new Date());
        log.info("合同信息：{}", contract);
        contractMapper.insert(contract);
        //新增记录
        String createBy = contract.getCreateBy();
        LambdaQueryWrapper<InsertRecord> wrapperC = new LambdaQueryWrapper<>();
        wrapperC.eq(BeanUtil.isNotEmpty(createBy),InsertRecord::getCreateBy,createBy);
        InsertRecord insertRecord = indexMapper.selectOne(wrapperC);
        if(insertRecord == null){
            throw new RuntimeException("新增记录失败");
        }else {
            insertRecord.setBusinessCount(insertRecord.getBusinessChangeCount()+1);
        }
        businessServicelmpl.deleteBusiness(id);
    }

}
